package com.gjt.serverSocket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class EchoServerChannel {
    public static int PORT = 7;

    public static void main(String[] args) {
        int port;
        try {
            port = Integer.parseInt(args[0]);
        } catch (RuntimeException e) {
            port = PORT;
        }
        System.out.println("Listening for connections on port " + port);
        ServerSocketChannel serverChannel;
        Selector selector;
        try {
            // 获取通道
            serverChannel = ServerSocketChannel.open();

            if(!serverChannel.isOpen()){
                System.out.println("通道没有打开");
                return;
            }

            // 在通道上获取socket
            ServerSocket socket = serverChannel.socket();
            InetSocketAddress address = new InetSocketAddress(port);

            // 通道和socket 绑定
            socket.bind(address);
            // 设置通道不阻塞
            serverChannel.configureBlocking(false);

            selector = Selector.open();

            if(!selector.isOpen()){
                System.out.println("选择器没有打开");
                return;
            }

            serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        while (true) {
            try {
                selector.select();
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }

            Iterator<SelectionKey> keys = selector.selectedKeys().iterator();


            while (keys.hasNext()) {
                SelectionKey key = keys.next();
                keys.remove();
                try {
                    if (key.isAcceptable()) {
                        ServerSocketChannel server = (ServerSocketChannel) key.channel();
                        SocketChannel client = server.accept();
                        System.out.println("Accepted connection from " + client);
                        client.configureBlocking(false);
                        SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                        ByteBuffer buffer = ByteBuffer.allocate(100);
                        clientKey.attach(buffer);
                    }
                    if (key.isReadable()) {
                        SocketChannel client = (SocketChannel) key.channel();
                        ByteBuffer output = (ByteBuffer) key.attachment();
                        client.read(output);

                        Charset charset = StandardCharsets.US_ASCII;
                        CharBuffer decode = charset.decode(output);
                        System.out.println(decode.toString());
                    }

                    if (key.isWritable()) {
                        SocketChannel client = (SocketChannel) key.channel();
                        ByteBuffer output = (ByteBuffer) key.attachment();

                        output.flip();
                        client.write(output);
                        output.compact();
                    }

                } catch (IOException ex) {
                    key.channel();
                    try {
                        key.channel().close();
                    } catch (IOException ignored) {
                    }
                }
            }

        }
    }
}
